home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_351 / pdc / libsrc.lzh / LibSrc / StdIO / format.c < prev    next >
C/C++ Source or Header  |  1990-04-07  |  6KB  |  276 lines

  1. /*
  2.  * Libraries and headers for PDC release 3.3 (C) 1989 Lionel Hummel.
  3.  * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
  4.  * PDC I/O Library (C) 1987 by J.A. Lydiatt.
  5.  *
  6.  * This code is freely redistributable upon the conditions that this 
  7.  * notice remains intact and that modified versions of this file not
  8.  * be included as part of the PDC Software Distribution without the
  9.  * express consent of the copyright holders.  No warrantee of any
  10.  * kind is provided with this code.  For further information, contact:
  11.  *
  12.  *  PDC Software Distribution    Internet:                     BIX:
  13.  *  P.O. Box 4006             or hummel@cs.uiuc.edu            lhummel
  14.  *  Urbana, IL  61801-8801       petersen@uicsrd.csrd.uiuc.edu
  15.  */
  16.  
  17. /*  format.c - routines for generating formatted strings
  18.  *
  19.  *  format - formats a string and outputs character
  20.  */
  21.  
  22. #include <limits.h>
  23.  
  24. static unsigned int base;
  25. static int minwidth, precision, padchar, rjust, nsent;
  26. static int (*put)();
  27.  
  28. /*
  29.  * putint: convert long to ascii. Return a pointer to start of string.
  30.  */
  31. static char digit[] = "0123456789ABCDEF";
  32.  
  33. static char *
  34. putint( str, n)
  35. char *str;
  36. long    n;
  37. {
  38.     char *s;
  39.     int is_negative;
  40.     unsigned int un;
  41.  
  42.     if (n == 0x80000000) {        /* special case */
  43.         switch (base) {
  44.         case 8:
  45.             s = "20000000000";
  46.             break;
  47.         case 10:
  48.             s = "-2147483648";
  49.             break;
  50.         case 16:
  51.             s = "80000000";
  52.             break;
  53.         default:
  54.             s = "-OOPS-";
  55.         }
  56.         return s;
  57.     }
  58.  
  59.     is_negative = ( base==10 && n<0 );
  60.     if ( is_negative )
  61.         n = -n;
  62.  
  63.     un = (unsigned int) n;
  64.  
  65.     s = &str[MAXSTRING];
  66.     *--s = '\0';
  67.     do {
  68.         *--s = digit[ un % base ];
  69.         un /= base;
  70.     }
  71.         while ( un && s > &str[1] );
  72.  
  73.     if ( is_negative )
  74.         *--s = '-';
  75.  
  76.     return s;
  77. }
  78.  
  79. /*
  80.  * prt: Does the justification and fill if required.
  81.  * Side Effects: updates nsent, destroys minwidth.
  82.  */
  83.  
  84. static int 
  85. prt( strbuf )
  86. char *strbuf;
  87. {
  88.  
  89.     extern int  strlen();
  90.     int i; 
  91.     int c;
  92.     int len = 1;
  93.     int strsize = strlen( strbuf );
  94.  
  95.     if ( strsize > precision )
  96.         strsize = precision;
  97.  
  98.     if ( rjust ) {
  99.         if ( padchar != ' ' && (c = *strbuf) == '-' || c == '+' ) {
  100.             if ( (*put)(c) == -1 )
  101.                 return -1;
  102.             ++len;
  103.             ++strbuf;
  104.             --strsize;
  105.         }
  106.  
  107.         while ( --minwidth >= strsize ) {
  108.             if ( (*put)(padchar) == -1 )
  109.                 return -1;
  110.             ++len;
  111.         }
  112.  
  113.     }
  114.  
  115.     for ( i=0; i < precision && (c = *strbuf++); ++i ){
  116.         if ( (*put)(c) == -1 )
  117.                 return -1;
  118.     }
  119.     len += i;
  120.  
  121.     /*
  122.      * Pad with blanks, if necessary.
  123.      */
  124.  
  125.     while ( len < minwidth ) {
  126.         if ( (*put)(' ') == -1 )
  127.            return -1;
  128.         ++len;
  129.     }
  130.  
  131.     nsent += len;
  132.     return len;
  133. }
  134.  
  135. format( psub, ctl, argptr )
  136. int (*psub)();        /* Address of a routine to put a character */
  137. char *ctl;            /* The control string. */
  138. char *argptr;         /* pointer to arguments */
  139. {
  140.     union {
  141.         short *hptr;
  142.         int  *iptr;
  143.         long *lptr;
  144.         char *cptr;
  145.         char **cptr2;
  146.     }  args;
  147.  
  148.     unsigned int argsize, c;
  149.     long l;
  150.     char *sptr;
  151.     char strbuf[MAXSTRING];
  152.  
  153.     put = psub;
  154.     args.cptr = argptr;
  155.     nsent = 0;
  156.     while ( c = *ctl )    {
  157.  
  158.         /*
  159.          * Just print any non '%' characters in control string.
  160.          */
  161.  
  162.         if ( c != '%' )    {
  163.             if ( (*psub)(c) == -1 )
  164.                 return -1;
  165.             ++ctl;
  166.             ++nsent;
  167.             continue;
  168.         }
  169.  
  170.         /*
  171.          * Or echo a single '%' for a control string of "%%".
  172.          */
  173.  
  174.         if ( (c = *++ctl) == '%' )    {
  175.             if ( (*psub)(c) == -1 )
  176.                 return -1;
  177.             ++ctl;
  178.             ++nsent;
  179.             continue;
  180.         }
  181.  
  182.         /*
  183.          * Start of a format specifier: "%-010.5ld" for example.
  184.          */
  185.  
  186.         rjust = 1;
  187.         argsize = sizeof(int);
  188.         minwidth = precision = 0;
  189.         padchar = ' ';
  190.  
  191.         if ( c == '-' )    {
  192.             rjust = 0;
  193.             c = *++ctl;
  194.         }
  195.  
  196.         if ( c == '0' )    {
  197.             padchar = '0';
  198.             c = *++ctl;
  199.         }
  200.  
  201.         if ( c == '*' )    {
  202.             minwidth = *args.iptr++;
  203.             c = *++ctl;
  204.         } else {
  205.             while ( '0' <= c && c <= '9' )    {
  206.                 minwidth += minwidth * 10 + c - '0';
  207.                 c = *++ctl;
  208.             }
  209.         }
  210.  
  211.         if ( c == '.' )    {
  212.             c = *++ctl;
  213.             if ( c == '*' ) {
  214.                 precision = *args.iptr++;
  215.                 c = *++ctl;
  216.             } else {
  217.                 while ( '0' <= c && c <= '9' ){
  218.                     precision += precision * 10 + c - '0';
  219.                     c = *++ctl;
  220.                 }
  221.             }
  222.         }
  223.  
  224.         if ( c == 'l' || c == 'L' )    {
  225.             argsize = sizeof(long);
  226.             c = *++ctl;
  227.         }
  228.         else if ( c == 'h' || c == 'H' ){
  229.             argsize = sizeof(short int);
  230.             c = *++ctl;
  231.         }
  232.  
  233.         /*
  234.          * We should be at a conversion specification character.
  235.          */
  236.  
  237.         if ( precision >= (MAXSTRING-2)  || precision == 0)
  238.             precision = (MAXSTRING-2);
  239.         base = 0;
  240.         ++ctl;
  241.  
  242.         switch(c)    {
  243.             case 'x': base += 8;        /* FALL-THROUGH */
  244.             case 'o': base += 8;
  245.             case 'd': if ( !base )
  246.                           base = 10;
  247.                       if ( argsize == 4 )
  248.                           l = *args.lptr++;
  249.                       else
  250.                           l = *args.hptr++;
  251.                       sptr = putint( strbuf, l );
  252.                       if ( prt( sptr ) == -1 )
  253.                           return -1;
  254.                       break;
  255.  
  256.             case 's': sptr = *args.cptr2++;
  257.                       if (minwidth)
  258.                           precision = minwidth;
  259.                       else
  260.                           precision = 32717;
  261.                       if ( prt( sptr ) == -1 )
  262.                           return -1;
  263.                       break;
  264.  
  265.             case 'c': c = *args.iptr++;
  266.  
  267.             default : strbuf[0] = c;
  268.                       strbuf[1] = '\0';
  269.                       if ( prt( strbuf ) == -1 )
  270.                           return -1;
  271.                       break;
  272.  
  273.         }
  274.     }
  275. }
  276.